home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / manage / snmp / cmu-snmp1.0 / snmplib / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-19  |  20.6 KB  |  894 lines

  1. /***********************************************************
  2.     Copyright 1989 by Carnegie Mellon University
  3.  
  4.                       All Rights Reserved
  5.  
  6. Permission to use, copy, modify, and distribute this software and its 
  7. documentation for any purpose and without fee is hereby granted, 
  8. provided that the above copyright notice appear in all copies and that
  9. both that copyright notice and this permission notice appear in 
  10. supporting documentation, and that the name of CMU not be
  11. used in advertising or publicity pertaining to distribution of the
  12. software without specific, written prior permission.  
  13.  
  14. CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  15. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  16. CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  17. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  18. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  19. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  20. SOFTWARE.
  21. ******************************************************************/
  22. /*
  23.  * parse.c
  24.  */
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include "parse.h"
  28.  
  29. /*
  30.  * This is one element of an object identifier with either an integer subidentifier,
  31.  * or a textual string label, or both.
  32.  * The subid is -1 if not present, and label is NULL if not present.
  33.  */
  34. struct subid {
  35.     int subid;
  36.     char *label;
  37. };
  38.  
  39. int Line = 1;
  40.  
  41. /* types of tokens */
  42. #define    CONTINUE    -1
  43. #define LABEL        1
  44. #define SUBTREE        2
  45. #define SYNTAX        3
  46. #define OBJID        4
  47. #define OCTETSTR    5
  48. #define INTEGER        6
  49. #define NETADDR        7
  50. #define    IPADDR        8
  51. #define COUNTER        9
  52. #define GAUGE        10
  53. #define TIMETICKS   11
  54. #define OPAQUE        12
  55. #define NUL        13
  56. #define SEQUENCE    14
  57. #define OF        15    /* SEQUENCE OF */
  58. #define OBJTYPE        16
  59. #define ACCESS        17
  60. #define READONLY    18
  61. #define READWRITE   19
  62. #define    WRITEONLY   20
  63. #define NOACCESS    21
  64. #define STATUS        22
  65. #define MANDATORY   23
  66. #define OPTIONAL    24
  67. #define OBSOLETE    25
  68. #define PUNCT        26
  69. #define EQUALS        27
  70.  
  71. struct tok {
  72.     char *name;            /* token name */
  73.     int len;            /* length not counting nul */
  74.     int token;            /* value */
  75.     int hash;            /* hash of name */
  76.     struct tok *next;        /* pointer to next in hash table */
  77. };
  78.  
  79.  
  80. struct tok tokens[] = {
  81.     { "obsolete", sizeof ("obsolete")-1, OBSOLETE },
  82.     { "Opaque", sizeof ("Opaque")-1, OPAQUE },
  83.     { "optional", sizeof ("optional")-1, OPTIONAL },
  84.     { "mandatory", sizeof ("mandatory")-1, MANDATORY },
  85.     { "not-accessible", sizeof ("not-accessible")-1, NOACCESS },
  86.     { "write-only", sizeof ("write-only")-1, WRITEONLY },
  87.     { "read-write", sizeof ("read-write")-1, READWRITE },
  88.     { "TimeTicks", sizeof ("TimeTicks")-1, TIMETICKS },
  89.     { "OBJECTIDENTIFIER", sizeof ("OBJECTIDENTIFIER")-1, OBJID },
  90.     /*
  91.      * This CONTINUE appends the next word onto OBJECT,
  92.      * hopefully matching OBJECTIDENTIFIER above.
  93.      */
  94.     { "OBJECT", sizeof ("OBJECT")-1, CONTINUE },
  95.     { "NetworkAddress", sizeof ("NetworkAddress")-1, NETADDR },
  96.     { "Gauge", sizeof ("Gauge")-1, GAUGE },
  97.     { "OCTETSTRING", sizeof ("OCTETSTRING")-1, OCTETSTR },
  98.     { "OCTET", sizeof ("OCTET")-1, -1 },
  99.     { "OF", sizeof ("OF")-1, OF },
  100.     { "SEQUENCE", sizeof ("SEQUENCE")-1, SEQUENCE },
  101.     { "NULL", sizeof ("NULL")-1, NUL },
  102.     { "IpAddress", sizeof ("IpAddress")-1, IPADDR },
  103.     { "INTEGER", sizeof ("INTEGER")-1, INTEGER },
  104.     { "Counter", sizeof ("Counter")-1, COUNTER },
  105.     { "read-only", sizeof ("read-only")-1, READONLY },
  106.     { "ACCESS", sizeof ("ACCESS")-1, ACCESS },
  107.     { "STATUS", sizeof ("STATUS")-1, STATUS },
  108.     { "SYNTAX", sizeof ("SYNTAX")-1, SYNTAX },
  109.     { "OBJECT-TYPE", sizeof ("OBJECT-TYPE")-1, OBJTYPE },
  110.     { "{", sizeof ("{")-1, PUNCT },
  111.     { "}", sizeof ("}")-1, PUNCT },
  112.     { "::=", sizeof ("::=")-1, EQUALS },
  113.     { NULL }
  114. };
  115.  
  116. #define    HASHSIZE    32
  117. #define    BUCKET(x)    (x & 0x01F)
  118.  
  119. struct tok    *buckets[HASHSIZE];
  120.  
  121. static
  122. hash_init()
  123. {
  124.     register struct tok    *tp;
  125.     register char    *cp;
  126.     register int    h;
  127.     register int    b;
  128.  
  129.     for (tp = tokens; tp->name; tp++) {
  130.         for (h = 0, cp = tp->name; *cp; cp++)
  131.             h += *cp;
  132.         tp->hash = h;
  133.         b = BUCKET(h);
  134.         if (buckets[b])
  135.             tp->next = buckets[b];
  136.         buckets[b] = tp;
  137.     }
  138. }
  139.  
  140.  
  141. static char *
  142. Malloc(num)
  143.     unsigned num;
  144. {
  145.     char *cp;
  146.     char *malloc();
  147.     
  148.     /* this is to fix (what seems to be) a problem with the IBM RT C library malloc */
  149.     if (num < 16)
  150.     num = 16;
  151.     cp = malloc(num);
  152.     return cp;
  153. }
  154.  
  155. static
  156. print_error(string, token)
  157.     char *string;
  158.     char *token;
  159. {
  160.     if (token)
  161.     fprintf(stderr, "%s(%s): On or around line %d\n", string, token, Line);
  162.     else
  163.     fprintf(stderr, "%s: On or around line %d\n", string, Line);
  164. }
  165.  
  166. #ifdef TEST
  167. print_subtree(tree, count)
  168.     struct tree *tree;
  169.     int count;
  170. {
  171.     struct tree *tp;
  172.     int i;
  173.  
  174.     for(i = 0; i < count; i++)
  175.     printf("  ");
  176.     printf("Children of %s:\n", tree->label);
  177.     count++;
  178.     for(tp = tree->child_list; tp; tp = tp->next_peer){
  179.     for(i = 0; i < count; i++)
  180.         printf("  ");
  181.     printf("%s\n", tp->label);
  182.     }
  183.     for(tp = tree->child_list; tp; tp = tp->next_peer){
  184.     print_subtree(tp, count);
  185.     }
  186. }
  187. #endif /* TEST */
  188.  
  189.  
  190. static struct tree *
  191. build_tree(nodes)
  192.     struct node *nodes;
  193. {
  194.     struct node *np;
  195.     struct tree *tp;
  196.     
  197.     /* build root node */
  198.     tp = (struct tree *)Malloc(sizeof(struct tree));
  199.     tp->parent = NULL;
  200.     tp->next_peer = NULL;
  201.     tp->child_list = NULL;
  202.     tp->enums = NULL;
  203.     strcpy(tp->label, "iso");
  204.     tp->subid = 1;
  205.     tp->type = 0;
  206.     /* grow tree from this root node */
  207.     do_subtree(tp, &nodes);
  208. #ifdef TEST
  209.     print_subtree(tp, 0);
  210. #endif /* TEST */
  211.     /* If any nodes are left, the tree is probably inconsistent */
  212.     if (nodes){
  213.     fprintf(stderr, "The mib description doesn't seem to be consistent.\n");
  214.     fprintf(stderr, "Some nodes couldn't be linked under the \"iso\" tree.\n");
  215.     fprintf(stderr, "these nodes are left:\n");
  216.     for(np = nodes; np; np = np->next)
  217.         fprintf(stderr, "%s ::= { %s %d } (%d)\n", np->label, np->parent, np->subid,
  218.             np->type);
  219.     }
  220.     return tp;
  221. }
  222.  
  223.  
  224. /*
  225.  * Find all the children of root in the list of nodes.  Link them into the
  226.  * tree and out of the nodes list.
  227.  */
  228. static
  229. do_subtree(root, nodes)
  230.     struct tree *root;
  231.     struct node **nodes;
  232. {
  233.     register struct tree *tp;
  234.     struct tree *peer = NULL;
  235.     register struct node *np;
  236.     struct node *oldnp = NULL, *child_list = NULL, *childp = NULL;
  237.     
  238.     tp = root;
  239.     /*
  240.      * Search each of the nodes for one whose parent is root, and
  241.      * move each into a seperate list.
  242.      */
  243.     for(np = *nodes; np; np = np->next){
  244.     if ((tp->label[0] == np->parent[0]) && !strcmp(tp->label, np->parent)){
  245.         if (child_list == NULL){
  246.         child_list = childp = np;   /* first entry in child list */
  247.         } else {
  248.         childp->next = np;
  249.         childp = np;
  250.         }
  251.         /* take this node out of the node list */
  252.         if (oldnp == NULL){
  253.         *nodes = np->next;  /* fix root of node list */
  254.         } else {
  255.         oldnp->next = np->next;    /* link around this node */
  256.         }
  257.     } else {
  258.         oldnp = np;
  259.     }
  260.     }
  261.     if (childp)
  262.     childp->next = 0;    /* re-terminate list */
  263.     /*
  264.      * Take each element in the child list and place it into the tree.
  265.      */
  266.     for(np = child_list; np; np = np->next){
  267.     tp = (struct tree *)Malloc(sizeof(struct tree));
  268.     tp->parent = root;
  269.     tp->next_peer = NULL;
  270.     tp->child_list = NULL;
  271.     strcpy(tp->label, np->label);
  272.     tp->subid = np->subid;
  273.     switch(np->type){
  274.         case OBJID:
  275.         tp->type = TYPE_OBJID;
  276.         break;
  277.         case OCTETSTR:
  278.         tp->type = TYPE_OCTETSTR;
  279.         break;
  280.         case INTEGER:
  281.         tp->type = TYPE_INTEGER;
  282.         break;
  283.         case NETADDR:
  284.         tp->type = TYPE_IPADDR;
  285.         break;
  286.         case IPADDR:
  287.         tp->type = TYPE_IPADDR;
  288.         break;
  289.         case COUNTER:
  290.         tp->type = TYPE_COUNTER;
  291.         break;
  292.         case GAUGE:
  293.         tp->type = TYPE_GAUGE;
  294.         break;
  295.         case TIMETICKS:
  296.         tp->type = TYPE_TIMETICKS;
  297.         break;
  298.         case OPAQUE:
  299.         tp->type = TYPE_OPAQUE;
  300.         break;
  301.         case NUL:
  302.         tp->type = TYPE_NULL;
  303.         break;
  304.         default:
  305.         tp->type = TYPE_OTHER;
  306.         break;
  307.     }
  308.     tp->enums = np->enums;
  309.     np->enums = NULL;    /* so we don't free them later */
  310.     if (root->child_list == NULL){
  311.         root->child_list = tp;
  312.     } else {
  313.         peer->next_peer = tp;
  314.     }
  315.     peer = tp;
  316.     do_subtree(tp, nodes);    /* recurse on this child */
  317.     }
  318.     /* free all nodes that were copied into tree */
  319.     for(np = child_list; np;){
  320.     oldnp = np;
  321.     np = np->next;
  322.     free_node(oldnp);
  323.     }
  324. }
  325.  
  326.  
  327. /*
  328.  * Takes a list of the form:
  329.  * { iso org(3) dod(6) 1 }
  330.  * and creates several nodes, one for each parent-child pair.
  331.  * Returns NULL on error.
  332.  */
  333. static int
  334. getoid(fp, oid,  length)
  335.     register FILE *fp;
  336.     register struct subid *oid;    /* an array of subids */
  337.     int length;        /* the length of the array */
  338. {
  339.     register int count;
  340.     int type;
  341.     char token[64], label[32];
  342.     register char *cp, *tp;
  343.  
  344.     if ((type = get_token(fp, token)) != PUNCT){
  345.     if (type == -1)
  346.         print_error("Unexpected EOF", (char *)NULL);
  347.     else
  348.         print_error("Unexpected", token);
  349.     return NULL;
  350.     }
  351.     if (*token != '{'){
  352.     print_error("Unexpected", token);
  353.     return NULL;
  354.     }
  355.     for(count = 0; count < length; count++, oid++){
  356.     oid->label = 0;
  357.     oid->subid = -1;
  358.     if ((type = get_token(fp, token)) != LABEL){
  359.         if (type == -1){
  360.         print_error("Unexpected EOF", (char *)NULL);
  361.         return NULL;
  362.         }
  363.         else if (type == PUNCT && *token == '}'){
  364.         return count;
  365.         } else {
  366.         print_error("Unexpected", token);
  367.         return NULL;
  368.         }
  369.     }
  370.     tp = token;
  371.     if (!isdigit(*tp)){
  372.         /* this entry has a label */
  373.         cp = label;
  374.         while(*tp && *tp != '(')
  375.         *cp++ = *tp++;
  376.         *cp = 0;
  377.         cp = (char *)Malloc((unsigned)strlen(label));
  378.         strcpy(cp, label);
  379.         oid->label = cp;
  380.         if (*tp == '('){
  381.         /* this entry has a label-integer pair in the form label(integer). */
  382.         cp = ++tp;
  383.         while(*cp && *cp != ')')
  384.             cp++;
  385.         if (*cp == ')')
  386.             *cp = 0;
  387.         else {
  388.             print_error("No terminating parenthesis", (char *)NULL);
  389.             return NULL;
  390.         }
  391.         oid->subid = atoi(tp);
  392.         }
  393.     } else {
  394.         /* this entry  has just an integer sub-identifier */
  395.         oid->subid = atoi(tp);
  396.     }
  397.     }
  398.     return count;
  399.  
  400.  
  401. }
  402.  
  403. static
  404. free_node(np)
  405.     struct node *np;
  406. {
  407.     struct enum_list *ep, *tep;
  408.  
  409.     ep = np->enums;
  410.     while(ep){
  411.     tep = ep;
  412.     ep = ep->next;
  413.     free((char *)tep);
  414.     }
  415.     free((char *)np);
  416. }
  417.  
  418. /*
  419.  * Parse an entry of the form:
  420.  * label OBJECT IDENTIFIER ::= { parent 2 }
  421.  * The "label OBJECT IDENTIFIER" portion has already been parsed.
  422.  * Returns 0 on error.
  423.  */
  424. static struct node *
  425. parse_objectid(fp, name)
  426.     FILE *fp;
  427.     char *name;
  428. {
  429.     int type;
  430.     char token[64];
  431.     register int count;
  432.     register struct subid *op, *nop;
  433.     int length;
  434.     struct subid oid[16];
  435.     struct node *np, *root;
  436.  
  437.     type = get_token(fp, token);
  438.     if (type != EQUALS){
  439.     print_error("Bad format", token);
  440.     return 0;
  441.     }
  442.     if (length = getoid(fp, oid, 16)){
  443.     np = root = (struct node *)Malloc(sizeof(struct node));
  444.     /*
  445.      * For each parent-child subid pair in the subid array,
  446.      * create a node and link it into the node list.
  447.      */
  448.     for(count = 0, op = oid, nop=oid+1; count < (length - 2); count++,
  449.         op++, nop++){
  450.         /* every node must have parent's name and child's name or number */
  451.         if (op->label && (nop->label || (nop->subid != -1))){
  452.         strcpy(np->parent, op->label);
  453.         if (nop->label)
  454.             strcpy(np->label, nop->label);
  455.         if (nop->subid != -1)
  456.             np->subid = nop->subid;
  457.         np ->type = 0;
  458.         np->enums = 0;
  459.         /* set up next entry */
  460.         np->next = (struct node *)Malloc(sizeof(*np->next));
  461.         np = np->next;
  462.         }
  463.     }
  464.     /*
  465.      * The above loop took care of all but the last pair.  This pair is taken
  466.      * care of here.  The name for this node is taken from the label for this
  467.      * entry.
  468.      * np still points to an unused entry.
  469.      */
  470.     if (count == (length - 2)){
  471.         if (op->label){
  472.         strcpy(np->parent, op->label);
  473.         strcpy(np->label, name);
  474.         if (nop->subid != -1)
  475.             np->subid = nop->subid;
  476.         else
  477.             print_error("Warning: This entry is pretty silly", token);
  478.         } else {
  479.         free_node(np);
  480.         }
  481.     } else {
  482.         print_error("Missing end of oid", (char *)NULL);
  483.         free_node(np);   /* the last node allocated wasn't used */
  484.         return NULL;
  485.     }
  486.     /* free the oid array */
  487.     for(count = 0, op = oid; count < length; count++, op++){
  488.         if (op->label)
  489.         free(oid->label);
  490.         op->label = 0;
  491.     }
  492.     return root;
  493.     } else {
  494.     print_error("Bad object identifier", (char *)NULL);
  495.     return 0;
  496.     }
  497. }
  498.  
  499. /*
  500.  * Parses an asn type.  This structure is ignored by this parser.
  501.  * Returns NULL on error.
  502.  */
  503. static int
  504. parse_asntype(fp)
  505.     FILE *fp;
  506. {
  507.     int type;
  508.     char token[64];
  509.  
  510.     type = get_token(fp, token);
  511.     if (type != SEQUENCE){
  512.     print_error("Not a sequence", (char *)NULL); /* should we handle this */
  513.     return NULL;
  514.     }
  515.     while((type = get_token(fp, token)) != NULL){
  516.     if (type == -1)
  517.         return NULL;
  518.     if (type == PUNCT && (token[0] == '}' && token[1] == '\0'))
  519.         return -1;
  520.     }
  521.     print_error("Premature end of file", (char *)NULL);
  522.     return NULL;
  523. }
  524.  
  525. /*
  526.  * Parses an OBJECT TYPE macro.
  527.  * Returns 0 on error.
  528.  */
  529. static struct node *
  530. parse_objecttype(fp, name)
  531.     register FILE *fp;
  532.     char *name;
  533. {
  534.     register int type;
  535.     char token[64];
  536.     int count, length;
  537.     struct subid oid[16];
  538.     char syntax[32];
  539.     int nexttype;
  540.     char nexttoken[64];
  541.     register struct node *np;
  542.     register struct enum_list *ep;
  543.     register char *cp;
  544.     register char *tp;
  545.  
  546.     type = get_token(fp, token);
  547.     if (type != SYNTAX){
  548.     print_error("Bad format for OBJECT TYPE", token);
  549.     return 0;
  550.     }
  551.     np = (struct node *)Malloc(sizeof(struct node));
  552.     np->next = 0;
  553.     np->enums = 0;
  554.     type = get_token(fp, token);
  555.     nexttype = get_token(fp, nexttoken);
  556.     np->type = type;
  557.     switch(type){
  558.     case SEQUENCE:
  559.         strcpy(syntax, token);
  560.         if (nexttype == OF){
  561.         strcat(syntax, " ");
  562.         strcat(syntax, nexttoken);
  563.         nexttype = get_token(fp, nexttoken);
  564.         strcat(syntax, " ");
  565.         strcat(syntax, nexttoken);
  566.         nexttype = get_token(fp, nexttoken);
  567.         }
  568.         break;
  569.     case INTEGER:
  570.         strcpy(syntax, token);
  571.         if (nexttype == PUNCT &&
  572.         (nexttoken[0] == '{' && nexttoken[1] == '\0')) {
  573.         /* if there is an enumeration list, parse it */
  574.         while((type = get_token(fp, token)) != NULL){
  575.             if (type == -1){
  576.             free_node(np);
  577.             return 0;
  578.             }
  579.             if (type == PUNCT &&
  580.             (token[0] == '}' && token[1] == '\0'))
  581.             break;
  582.             if (type == 1){
  583.             /* this is an enumerated label */
  584.             if (np->enums == 0){
  585.                 ep = np->enums = (struct enum_list *)
  586.                     Malloc(sizeof(struct enum_list));
  587.             } else {
  588.                 ep->next = (struct enum_list *)
  589.                     Malloc(sizeof(struct enum_list));
  590.                 ep = ep->next;
  591.             }
  592.             ep->next = 0;
  593.             /* a reasonable approximation for the length */
  594.             ep->label = (char *)Malloc((unsigned)strlen(token));
  595.             cp = ep->label;
  596.             tp = token;
  597.             while(*tp != '(')
  598.                 *cp++ = *tp++;
  599.             *cp = 0;
  600.             cp = ++tp;    /* start of number */
  601.             while(*tp != ')')
  602.                 tp++;
  603.             *tp = 0;    /* terminate number */
  604.             ep->value = atoi(cp);
  605.             }
  606.         }
  607.         if (type == NULL){
  608.             print_error("Premature end of file", (char *)NULL);
  609.             free_node(np);
  610.             return 0;
  611.         }
  612.         nexttype = get_token(fp, nexttoken);
  613.         } else if (nexttype == LABEL && *nexttoken == '('){
  614.         /* ignore the "constrained integer" for now */
  615.         nexttype = get_token(fp, nexttoken);
  616.         }
  617.         break;
  618.     case OBJID:
  619.     case OCTETSTR:
  620.     case NETADDR:
  621.     case IPADDR:
  622.     case COUNTER:
  623.     case GAUGE:
  624.     case TIMETICKS:
  625.     case OPAQUE:
  626.     case NUL:
  627.     case LABEL:
  628.         strcpy(syntax, token);
  629.         break;
  630.     default:
  631.         print_error("Bad syntax", token);
  632.         free_node(np);
  633.         return 0;
  634.     }
  635.     if (nexttype != ACCESS){
  636.     print_error("Should be ACCESS", nexttoken);
  637.     free_node(np);
  638.     return 0;
  639.     }
  640.     type = get_token(fp, token);
  641.     if (type != READONLY && type != READWRITE && type != WRITEONLY
  642.     && type != NOACCESS){
  643.     print_error("Bad access type", nexttoken);
  644.     free_node(np);
  645.     return 0;
  646.     }
  647.     type = get_token(fp, token);
  648.     if (type != STATUS){
  649.     print_error("Should be STATUS", token);
  650.     free_node(np);
  651.     return 0;
  652.     }
  653.     type = get_token(fp, token);
  654.     if (type != MANDATORY && type != OPTIONAL && type != OBSOLETE){
  655.     print_error("Bad status", token);
  656.     free_node(np);
  657.     return 0;
  658.     }
  659.     type = get_token(fp, token);
  660.     if (type != EQUALS){
  661.     print_error("Bad format", token);
  662.     free_node(np);
  663.     return 0;
  664.     }
  665.     length = getoid(fp, oid, 16);
  666.     if (length > 1 && length <= 16){
  667.     /* just take the last pair in the oid list */
  668.     if (oid[length - 2].label)
  669.         strncpy(np->parent, oid[length - 2].label, 32);
  670.     strcpy(np->label, name);
  671.     if (oid[length - 1].subid != -1)
  672.         np->subid = oid[length - 1].subid;
  673.     else
  674.         print_error("Warning: This entry is pretty silly", (char *)NULL);
  675.     } else {
  676.     print_error("No end to oid", (char *)NULL);
  677.     free_node(np);
  678.     np = 0;
  679.     }
  680.     /* free oid array */
  681.     for(count = 0; count < length; count++){
  682.     if (oid[count].label)
  683.         free(oid[count].label);
  684.     oid[count].label = 0;
  685.     }
  686.     return np;
  687. }
  688.  
  689.  
  690. /*
  691.  * Parses a mib file and returns a linked list of nodes found in the file.
  692.  * Returns NULL on error.
  693.  */
  694. static struct node *
  695. parse(fp)
  696.     FILE *fp;
  697. {
  698.     char token[64];
  699.     char name[32];
  700.     int    type = 1;
  701.     struct node *np, *root = NULL;
  702.  
  703.     hash_init();
  704.  
  705.     while(type != NULL){
  706.     type = get_token(fp, token);
  707.     if (type != LABEL){
  708.         if (type == NULL){
  709.         return root;
  710.         }
  711.         print_error(token, "is a reserved word");
  712.         return NULL;
  713.     }
  714.     strncpy(name, token, 32);
  715.     type = get_token(fp, token);
  716.     if (type == OBJTYPE){
  717.         if (root == NULL){
  718.         /* first link in chain */
  719.         np = root = parse_objecttype(fp, name);
  720.         if (np == NULL){
  721.             print_error("Bad parse of object type", (char *)NULL);
  722.             return NULL;
  723.         }
  724.         } else {
  725.         np->next = parse_objecttype(fp, name);
  726.         if (np->next == NULL){
  727.             print_error("Bad parse of objecttype", (char *)NULL);
  728.             return NULL;
  729.         }
  730.         }
  731.         /* now find end of chain */
  732.         while(np->next)
  733.         np = np->next;
  734.     } else if (type == OBJID){
  735.         if (root == NULL){
  736.         /* first link in chain */
  737.         np = root = parse_objectid(fp, name);
  738.         if (np == NULL){
  739.             print_error("Bad parse of object id", (char *)NULL);
  740.             return NULL;
  741.         }
  742.         } else {
  743.         np->next = parse_objectid(fp, name);
  744.         if (np->next == NULL){
  745.             print_error("Bad parse of object type", (char *)NULL);
  746.             return NULL;
  747.         }
  748.         }
  749.         /* now find end of chain */
  750.         while(np->next)
  751.         np = np->next;
  752.     } else if (type == EQUALS){
  753.         type = parse_asntype(fp);
  754.     } else if (type == NULL){
  755.         break;
  756.     } else {
  757.         print_error("Bad operator", (char *)NULL);
  758.         return NULL;
  759.     }
  760.     }
  761. #ifdef TEST
  762. {
  763.     struct enum_list *ep;
  764.     
  765.     for(np = root; np; np = np->next){
  766.     printf("%s ::= { %s %d } (%d)\n", np->label, np->parent, np->subid,
  767.         np->type);
  768.     if (np->enums){
  769.         printf("Enums: \n");
  770.         for(ep = np->enums; ep; ep = ep->next){
  771.         printf("%s(%d)\n", ep->label, ep->value);
  772.         }
  773.     }
  774.     }
  775. }
  776. #endif /* TEST */
  777.     return root;
  778. }
  779.  
  780. /*
  781.  * Parses a token from the file.  The type of the token parsed is returned,
  782.  * and the text is placed in the string pointed to by token.
  783.  */
  784. static int
  785. get_token(fp, token)
  786.     register FILE *fp;
  787.     register char *token;
  788. {
  789.     static char last = ' ';
  790.     register int ch;
  791.     register char *cp = token;
  792.     register int hash = 0;
  793.     register struct tok *tp;
  794.  
  795.     *cp = 0;
  796.     ch = last;
  797.     /* skip all white space */
  798.     while(isspace(ch) && ch != -1){
  799.     ch = getc(fp);
  800.     if (ch == '\n')
  801.         Line++;
  802.     }
  803.     if (ch == -1)
  804.     return NULL;
  805.  
  806.     /*
  807.      * Accumulate characters until white space is found.  Then attempt to match this
  808.      * token as a reserved word.  If a match is found, return the type.  Else it is
  809.      * a label.
  810.      */
  811.     do {
  812.     if (!isspace(ch)){
  813.         hash += ch;
  814.         *cp++ = ch;
  815.         if (ch == '\n')
  816.         Line++;
  817.     } else {
  818.         last = ch;
  819.         *cp = '\0';
  820.  
  821.         for (tp = buckets[BUCKET(hash)]; tp; tp = tp->next) {
  822.         if ((tp->hash == hash) && (strcmp(tp->name, token) == 0))
  823.             break;
  824.         }
  825.         if (tp){
  826.         if (tp->token == CONTINUE)
  827.             continue;
  828.         return (tp->token);
  829.         }
  830.  
  831.         if (token[0] == '-' && token[1] == '-'){
  832.         /* strip comment */
  833.         while ((ch = getc(fp)) != -1)
  834.             if (ch == '\n'){
  835.             Line++;
  836.             break;
  837.             }
  838.         if (ch == -1)
  839.             return NULL;
  840.         last = ch;
  841.         return get_token(fp, token);        
  842.         }
  843.         return LABEL;
  844.     }
  845.     
  846.     } while ((ch = getc(fp)) != -1);
  847.     return NULL;
  848. }
  849.  
  850. struct tree *
  851. read_mib(filename)
  852.     char *filename;
  853. {
  854.     FILE *fp;
  855.     struct node *nodes;
  856.     struct tree *tree;
  857.     struct node *parse();
  858.  
  859.     fp = fopen(filename, "r");
  860.     if (fp == NULL)
  861.     return NULL;
  862.     nodes = parse(fp);
  863.     if (!nodes){
  864.     fprintf(stderr, "Mib table is bad.  Exiting\n");
  865.     exit(1);
  866.     }
  867.     tree = build_tree(nodes);
  868.     fclose(fp);
  869.     return tree;
  870. }
  871.  
  872.  
  873. #ifdef TEST
  874. main(argc, argv)
  875.     int argc;
  876.     char *argv[];
  877. {
  878.     FILE *fp;
  879.     struct node *nodes;
  880.     struct tree *tp;
  881.  
  882.     fp = fopen("mib.txt", "r");
  883.     if (fp == NULL){
  884.     fprintf(stderr, "open failed\n");
  885.     return 1;
  886.     }
  887.     nodes = parse(fp);
  888.     tp = build_tree(nodes);
  889.     print_subtree(tp, 0);
  890.     fclose(fp);
  891. }
  892.  
  893. #endif /* TEST */
  894.